﻿using Microsoft.Graph.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zhaoxi.Industrial.BLL;
using Zhaoxi.Industrial.Model;
using ZhaoXi.Communication;
using ZhaoXi.Communication.ModBus;

namespace Zhaoxi.Industrial.Base
{
    public class GobalMonitor
    {
        //存储区 数据
        public static List<StorageModel> StorageList { get; set; }

        //主机区 数据
        public static List<DeviceModel> DeviceList { get; set; }

        //串口初始化
        public static SerialInfo SerialCom { get; set; }

        //新建一个静态字段用以控制循环是否继续
        public static bool Status = true;

        //建立线程用以启动
        public static Task task = null;

        //创建全局RTU 实例 
        public static RTU _RTU = null;

        public static void Start(Action action_success,Action<string> action_fail)
        {
            task = Task.Run(async () =>
            {
                IndustrialBLL bll = new IndustrialBLL();
                //初始化串口信息
                var serial = bll.InitSerialInfo();
                if (serial.Status)
                {
                    SerialCom = serial.Data;
                }
                else
                {
                    action_fail(serial.Message);
                }

                //初始化存储区的数据
                var storage = bll.DataInitStorge();
                if (storage.Status)
                {
                    StorageList = storage.Data;
                }
                else
                {
                    action_fail(storage.Message);
                }


                //初始化设备列表
                var device = bll.DataInitDevice();
                if (device.Status)
                {
                    DeviceList = device.Data;
                }
                else
                {
                    action_fail(device.Message);
                }

                _RTU = RTU.getInstatnce(SerialCom);
                _RTU.Response = new Action<int, List<byte>>(PasringData);
                if (_RTU.Connection())
                {
                    action_success();

                    int startaddress = 0;
                    while (Status)
                    {
                        foreach (var item in StorageList)
                        {
                            if (item.length > 100)
                            {
                                startaddress = item.start_address;
                                int readCount = item.length / 100;//modbus 单词请求最大值125  这边设置100用模拟一下
                                for (int i = 0; i < readCount; i++)
                                {
                                    int readLen = i == readCount ? item.length - 100 * i : 100;
                                    await _RTU.send(item.slave_id,(byte)item.fun_code,startaddress + 100 * i,readLen);
                                }
                            }

                            if (item.length % 100 > 0)
                            {
                                await _RTU.send(item.slave_id, (byte)item.fun_code, startaddress + 100 * (item.length / 100), item.length % 100);
                            }
                        }
                    }
                }
                else { 
                    action_fail("串口初始化失败，请检查原因！"); ;
                }
            });
        }

        public static void PasringData(int start_address, List<byte> bytes) {
            if (bytes != null && bytes.Count> 0 )
            {
                //查找设备监控点位与当前返回报文相关的监控数据列表
                //根据从站地址、功能码、起始地址
                var mvl = (from q in DeviceList //遍历设备表
                           from m in q.monitorValues //从设备表中 遍历关联表 
                           where m.storage_area_id == (bytes[0].ToString() + bytes[1].ToString("00") + start_address.ToString())   // && q.isRunning 找到关联表中从机地址并匹配上目标从机，格式为（从机、功能码、起始地址），还有一个条件是主机要在运转
                           select m
                           ).ToList();

                int startByte;
                byte[] res = null;
                foreach (var item in mvl)
                {
                    switch (item.datatype)//判断存取的数据类型
                    {
                        case "Float":
                            startByte = item.address * 2 + 3;//这里代表的是 功能码 从机地址  起始地址 数据长度。这里的加3是为因为FLOAT是2个字节 8位  +3是为了完整的读完一组数据。
                            if (startByte < start_address + bytes.Count)
                            {
                                //正好是4个字符
                                res = new byte[4] { bytes[startByte], bytes[startByte + 1], bytes[startByte + 2], bytes[startByte + 3] };
                                item.content = Convert.ToDouble(res.ByteArrsyToFloat());
                            }
                            break;
                        default:
                            break;
                    }
                }
            } 
        }


        public static void Dispose() { 
            Status= false;

            if (task != null)
            {
                task.Wait();
            }

            if (_RTU != null)
            {
                _RTU.Dispose();
            }
        }
        
    }
}
